/**公共工具包(by WangSong)*/
//使用ID获取对象引用
var WEB_URL="/biplam";
var AJXSERVER="/ajxServer";
var $ = function (id) {
    return "string" == typeof id ? document.getElementById(id) : id;
};

//复制数组(destination, source)
var ArrayCopy = function(destination, source) {
	for (var property in source) {
		destination[property] = source[property];
	}
	return destination;
};

//遍历传入对象数组，将该对象传入回调函数callback
var forEach = function(array, callback, param1,param2,param3,param4){
	if(array.forEach){
		array.forEach(callback,param1,param2,param3,param4);
	}else{
		for (var i = 0, len = array.length; i < len; i+=1) { callback.call(null, array[i], param1,param2,param3,param4); }
	}
};

//动态实例绑定函数
var Bind = function(object, fun) {
	var args = Array.prototype.slice.call(arguments).slice(2);
	return function() {
		return fun.apply(object, args.concat(Array.prototype.slice.call(arguments)));
	};
};

//事件注册表原型类
var registPools=function(){
	this.pool=new Array();
};
registPools.prototype={
	//放入某个对象某个事件的绑定项
	put:function(oId,eId,item){
		//search
		var items=new Array();
		var i=0;
		for(var len=this.pool.length;i<len;){
			if(this.pool[i][0]==oId && this.pool[i][1]==eId){
				items=this.pool[i][2];
				break;
			}
			i+=1;
		}
		//增加绑定项
		if(items.length>0){//founded
			items.push(item);
		}else{
			items.push(item);
			var poolItem=new Array(oId,eId,items);
			this.pool.push(poolItem);
		}
	},
	bind:function(){
		var evl;
		for(var i=0,len=this.pool.length;i<len;i+=1){
			evl="$('"+this.pool[i][0]+"')."+this.pool[i][1]+"=function(){";
			for(var j=0,len2=this.pool[i][2].length;j<len2;j+=1){
				evl+=this.pool[i][2][j];
			}
			evl+="};";
			eval(evl);
		}
		this.clear();
	},
	clear:function(){
		this.pool.splice(0,this.pool.length);
	},
	print:function(){
	    var pst="";
		for(var i=0;i<this.pool.length;i+=1){
			pst+="object="+this.pool[i][0];
			pst+=",event="+this.pool[i][1];
			pst+=",script=";
			for(var j=0;j<this.pool[i][2].length;j+=1){
				pst+=" "+this.pool[i][2][j];
			}
			pst+="\n";
		}
		return pst;
	}
};

//事件注册表实例类
var rt=new registPools();

var setHtml=function(oId,html){
	if($(oId)){
		$(oId).innerHTML=html;
	}else{
		throw new Error("写入Html失败: "+oId+"  并非有效DOM对象!");
	}
};

var setText=function(oId,text){
	$(oId).innerText=text;
};

var setBind=function(script){
	eval(script);
	rt.bind();
};

/**通讯工具包(by WangSong)
通讯模式：
1.1. 自刷新(页面对象的自我刷新)/异步		1.2. 菜单点击(按点击项刷新目标区域)/同步
	适用于	VC                              	适用于	VC                          
	提供		容器ID                          		提供		容器ID                      
			actID                               		actID                           
	数据		主键id(放在容器内ID=cid+'r')    				主键ID                          
	脚本格式:	r(cid,aid)                      			目标容器ID                      
	返回	innerHtml+script                		脚本格式: m(cid,aid,rid,tid)        
                                            	返回	html+script                 

2.1. 无弹出的数据提交/同步					2.2. 有弹出的数据提交/同步                             
	适用于	VC                              	适用于	VC,DC                                      
	提供		容器ID                          		提供		容器ID                                     
			actID                               		actID                                          
	数据		主键id(放在容器内ID=cid+'r')    				弹出窗口级别[1-7]                              
	脚本格式: a(cid,aid)                    		数据		主键id(放在容器内ID=cid+'r')               
	返回	script			                		脚本格式: p(cid,aid,level,[flag])                           
	                                        	返回	html+script  

3.1. 弹出窗口内的数据提交/同步
	适用于	VC,DC
	提供		容器ID
			actID
			父容器ID
	数据		主键id(放在容器内ID=cid+'r')
	脚本格式: sp(cid,aid,pid)
	返回	script(级联刷新的脚本)

容器内数据参数要求
  1、全部用input类型保存数据(仅解析input类型的html dom对象);
  2、Input type=text/password的,其name是字段名,value是字段值;
  3、Input type=hidden的,其name为逗号分隔的各段,第二段是字段名,如:name="c,flag"(c表示checkbox,flag为字段名);
*/
var loading=function(tid){
$(tid).innerHTML="<SPAN class='st' style='padding-top:3px'>装载中...</span>";
};
/**自刷新*/
var r=function(cid,aid){
	if(null==uid){if($('userid')){uid=$('userid').value;}}
	if(!($(cid))){throw new Error("AjxR初始化失败: 需要ContainerID!");}
	if($(cid+'r')){
		var aGet=new xmlHttp(WEB_URL,AJXSERVER);
		aGet.Get(cid,aid,uid,$(cid+'r').value,cid,new ag(aGet));
	}else{
		throw new Error("AjxR初始化失败: 主键对象不存在!");
	}
};
/**异步刷新目标区域*/
var ma=function(cid,aid,tid){
	if(null==uid){if($('userid')){uid=$('userid').value;}}
	if(!($(cid))){throw new Error("AjxR初始化失败: 需要ContainerID!");}
	if($(cid+'r')){
		var aGet=new xmlHttp(WEB_URL,AJXSERVER);
		aGet.Get(cid,aid,uid,$(cid+'r').value,tid,new ag(aGet));
	}else{
		throw new Error("AjxR初始化失败: 主键对象不存在!");
	}
};
/**伪同步刷新目标区域*/
var m=function(cid,aid,rid,tid,otherContainer){
	if(null==uid){if($('userid')){uid=$('userid').value;}}
	if(!($(cid))){throw new Error("AjxM初始化失败: 需要ContainerID!");}
	if(!(tid)){throw new Error("AjxM初始化失败: 需要TargetID!");}
	if(!(rid)){throw new Error("AjxM初始化失败: 需要RecordID!");}
	ajxPost=new xmlHttp(WEB_URL,AJXSERVER);
	ajxPost.xml.onreadystatechange=new AjxGet().get;
	if(otherContainer){
		ajxPost.Post(cid,aid,uid,rid,tid,1,0,otherContainer);
	}else{
		ajxPost.Post(cid,aid,uid,rid,tid,1);
	}
	loading(tid);
};

/**同步刷新目标区域*/
var ms=function(cid,aid,rid,tid,otherContainer){
	if(null==uid){if($('userid')){uid=$('userid').value;}}
	if(!($(cid))){throw new Error("AjxMs初始化失败: 需要ContainerID(cid="+cid+",aid="+aid+")!");}
	if(!(tid)){throw new Error("AjxMs初始化失败: 需要TargetID!");}
	if(!(rid)){throw new Error("AjxMs初始化失败: 需要RecordID!");}
	if(otherContainer){
		ajxPostS.PostS(cid,aid,uid,rid,tid,1,0,otherContainer);
	}else{
		ajxPostS.PostS(cid,aid,uid,rid,tid,1);
	}
	appS(ajxPostS.xml.responseText,tid);
};


/**同步自刷新 增加对textarea提交的控制 flag=1时input和textarea都提交 flag=2时只提交input不提交textarea*/
var a=function(cid,aid,flag,rid){
	if(null==uid){if($('userid')){uid=$('userid').value;}}
	if(!($(cid))){throw new Error("AjxA初始化失败: 需要ContainerID!");}
	if(!(rid)){
		if($(cid+'r')){
			ajxPostS.PostS(cid,aid,uid,$(cid+'r').value,cid,flag);
		}else{
			throw new Error("AjxA初始化失败: 主键对象不存在!");
		}
	}else{
		ajxPostS.PostS(cid,aid,uid,rid,cid,flag);
	}
	appS(ajxPostS.xml.responseText,cid);
};

/**Popup弹出的数据提交/伪同步
level: 1-7
flag:[1/0]是否提交数据
*/
var p=function(cid,aid,level,flag){
	if(null==uid){if($('userid')){uid=$('userid').value;}}
	if(!(level)){throw new Error("AjxP初始化失败: 需要弹出层次!");}
	if((!$("syspop"+level))){throw new Error("AjxP初始化失败: 需要Popup窗口容器!");}
	/**同步通讯*/
	AjxScript="popupShow('syspop"+level+"');";
	if($(cid+'r')){
	    $('syspop'+level).onresize=null;
		ajxPostS.PostS(cid,aid,uid,$(cid+'r').value,"syspop"+level+"fc",flag);
		app(ajxPostS.xml.responseText);
	}else{
		throw new Error("AjxP初始化失败: 主键对象不存在!");
	}
};
/**Prompt弹出的数据提交/同步
flag:[1/0]是否提交数据
otherContainer:其他需要提交数据的容器 add by wangsong
*/
var pr=function(cid,aid,flag,otherContainer){
	if(null==uid){if($('userid')){uid=$('userid').value;}}
	if((!$("prompt"))){throw new Error("AjxPr初始化失败: 需要Prompt窗口容器!");}
	$("promptfbs").onclick=null;
	/**同步通讯*/
	AjxScript="promptShow('prompt');";
	if($(cid+'r')){
		$('promptfc').onresize=null;//清理onresize绑定
		ajxPostS.PostS(cid,aid,uid,$(cid+'r').value,"promptfc",flag,1,otherContainer);
		app(ajxPostS.xml.responseText);
	}else{
		throw new Error("AjxPr初始化失败: 主键对象不存在!");
	}
};
/**
	弹出窗口内的数据提交/同步
	cid:弹出窗口容器id
	aid:弹出窗口行为id
	pid:弹出窗口父容器id
	flag:是否刷新父页面 0不刷新 1刷新
	addParam:1:提交隐藏rid 0:提交附加参数
		附加参数:可附加多个参数,每个参数是一个字符串，代表一个键值对,中间逗号分隔，如：‘rid,1001’
*/
var sp = function(cid,aid,pid,flag,addParam,otherContainer){
	if(null==uid){if($('userid')){uid=$('userid').value;}}
	/**同步通讯*/
	if(addParam===0 || addParam==='0'){/**增加对额外参数的处理*/
		ajxPostS.param="";
		for(var i=5;i<arguments.length;i+=1){
			if(arguments[i].split(",").length>1){
				ajxPostS.addParam(arguments[i].split(",")[0],arguments[i].split(",")[1]);
			}
		}
		ajxPostS.PostS(cid,aid,uid,null,pid,1,addParam,ajxPostS.param);
	}else{
		if(!$(cid+'r')){throw new Error("AjxSp初始化失败: 需要RecordID!");}
		ajxPostS.PostS(cid,aid,uid,$(cid+'r').value,pid,1,addParam,otherContainer);
	}
	if(flag==1){
		app(ajxPostS.xml.responseText);
	}else{
		apj(ajxPostS.xml.responseText);
	}
};
/**PopView弹出的数据提交/同步
flag:[1/0]是否提交数据
otherContainer:其他需要提交数据的容器 add by wangsong
*/
var pv=function(cid,aid,flag,mouseFollow,otherContainer){
	if(null==uid){if($('userid')){uid=$('userid').value;}}
	if((!$("popview"))){throw new Error("AjxPv初始化失败: 需要Prompt窗口容器!");}
	/**伪同步通讯*/
	ajxPost=new xmlHttp(WEB_URL,AJXSERVER);
	AjxScript="popviewShow('popview',"+mouseFollow+");";
	ajxPost.xml.onreadystatechange=new AjxGet().get;
	if($(cid+'r')){
		$('popviewfc').onresize=null;//清理onresize绑定
		ajxPost.Post(cid,aid,uid,$(cid+'r').value,"popviewfc",flag,1,otherContainer);
	}else{
		throw new Error("AjxPv初始化失败: 主键对象不存在!");
	}
};

/**PopMenu弹出的数据提交/同步
flag:[1/0]是否提交数据
otherContainer:其他需要提交数据的容器 add by wangsong
*/
var pm=function(cid,aid,flag,mouseFollow,otherContainer){
	if(null==uid){if($('userid')){uid=$('userid').value;}}
	if((!$("popmenu"))){throw new Error("AjxPm初始化失败: 需要Prompt窗口容器!");}
	/**同步通讯*/
	AjxScript="popmenuShow('popmenu',"+mouseFollow+");";
	if($(cid+'r')){
		$('popmenufc').onresize=null;//清理onresize绑定
		ajxPostS.PostS(cid,aid,uid,$(cid+'r').value,"popmenufc",flag,1,otherContainer);
		app(ajxPostS.xml.responseText);
	}else{
		throw new Error("AjxPm初始化失败: 主键对象不存在!");
	}
};

/**持久化父页面刷新 增加对textarea提交的控制 flag=1时input和textarea都提交 flag=2时只提交input不提交textarea*/
var pa=function(cid,rid,flag){
	a(cid,getAid($(cid).getElementsByTagName('input')),rid,flag);
};
/**PopFloat弹出的数据提交-异步
followCid:跟随的容器id,以此容器左上角为坐标
*/
var pf=function(cid,aid,rid,followCid){
	if(!($(cid))){throw new Error("AjxPf初始化失败: 需要Container窗口容器("+cid+")");}
	if(null==uid){if($('userid')){uid=$('userid').value;}}
	if((!$("popfloat"))){throw new Error("AjxPf初始化失败: 需要PopFloat窗口容器!");}
	/**异步通讯*/
	AjxScript="popfloatShow('popfloat','"+followCid+"');";
	$('popfloat').onresize=null;
	if(!(rid)){
		if($(cid+'r')){
			ajxPostS.PostS(cid,aid,uid,$(cid+'r').value,"popfloatfc",1);
			app(ajxPostS.xml.responseText);
		}else{
			throw new Error("AjxPf初始化失败: 主键对象不存在!");
		}
	}else{
		ajxPostS.PostS(cid,aid,uid,rid,"popfloatfc",1);
		app(ajxPostS.xml.responseText);
	}
};

/**从父页面取aid*/
var getAid=function(x){
  for (var i = 0; i < x.length; i+=1) {
	if(x[i].id){
		if(x[i].id==".aid"){
			return x[i].value;
		}
	}
  }
  throw new Error("AjxPa初始化失败: aid为空!");
};

/**通讯返回数据处理函数(负责检测异步通讯实例状态,处理返回数据)*/

/**同步数据处理*/
var appS=function(text,tid){
	if(null==text){throw new Error("AjxAppS数据处理失败: 返回结果为空!");}
	if(!($(tid))){throw new Error("AjxAppS数据处理失败: 目标对象不存在!("+tid+")");}
	if(text.indexOf("<ajxh")>=0){//替换innerHtml
		setHtml(tid,text.substring(text.indexOf("<ajxh")+5));
	}
	apj(text);
};
/**伪同步数据处理*/
var app=function(text){
	if(null==text){throw new Error("AjxApp数据处理失败: 返回结果为空!");}
	if(text.indexOf("<ajxt")<0){
		throw new Error("AjxApp数据处理失败: 需要TargetID");
	}
	ajxTarget=text.substring(5,text.indexOf("ajxt>"));
	if(!($(ajxTarget))){throw new Error("AjxApp数据处理失败: 目标对象不存在!("+ajxTarget+")");}
	if(text.indexOf("<ajxh")>=0){//替换innerHtml
		setHtml(ajxTarget,text.substring(text.indexOf("<ajxh")+5));
	}
	apj(text);
};
/**处理返回数据的脚本*/
var apj=function(text){
	if(null==text){throw new Error("AjxApj数据处理失败: 返回结果为空!");}
	if(text.indexOf("<ajxb")>0){//绑定脚本
		setBind(text.substring(text.indexOf("<ajxb")+5,text.indexOf("ajxb>")));
	}
	if(AjxScript!==null){//用于执行弹出窗口脚本
		eval(AjxScript);
		AjxScript=null;
	}
	if(p_func!==null){//有后刷新绑定(页面对象刷新脚本中指定的需要在页面对象调整后执行的刷新函数)
		p_func.call();
		p_func=null;//释放p_func,以便下次使用
	}
};

/**异步通讯数据获取函数(负责检测异步通讯实例状态,处理返回数据)*/
var ag=function(handlerOb){
	eval("mouseX=getMousePos().x;");
	eval("mouseY=getMousePos().y;");
	this.init(handlerOb);
};
ag.prototype={
	handler:null,
	get:function(hh){
		if(this.handler.xml.readyState != 4 || this.handler.xml.status != 200){
			return;
		}
		app(this.handler.xml.responseText);
	},
	init:function(handler){
		this.handler = handler;
	},
	bind:function(){
		return Bind(this,this.get);
	}
};
/**@功能: 异步ajx数据处理(返回的数据)*/
var ap=function(text){
	if(null==text){throw new Error("Ajx数据处理失败: 返回结果为空!");}
	if(text.indexOf("<ajxt")<0){
		throw new Error("Ajx数据处理失败: 需要TargetID");
	}
	if(text.indexOf("<ajxh")>=0){//替换innerHtml
		setHtml(text.substring(5,text.indexOf("ajxt>")),text.substring(text.indexOf("<ajxh")+5));
	}
	if(text.indexOf("<ajxb")>0){//绑定脚本
		setBind(text.substring(text.indexOf("<ajxb")+5,text.indexOf("ajxb>")));
	}
};

/***************************************************/
/**AjxGet 伪同步通讯结果处理基础类*/
var AjxScript=null;
var mouseX,mouseY;
var AjxGet=function(){
	eval("mouseX=getMousePos().x;");
	eval("mouseY=getMousePos().y;");
	$("syswait").style.visibility="visible";
};
AjxGet.prototype={
	get:function(){
		if(ajxPost.xml.readyState != 4 || ajxPost.xml.status != 200){
			return;
		}
		app(ajxPost.xml.responseText);
		$("syswait").style.visibility="hidden";
	},
	getScript:function(){//用于sp提交后的自定义脚本刷新
		apj(ajxPost.xml.responseText);
		$("syswait").style.visibility="hidden";
	}
};

/***************************************************/
/**xmlHttp Class(同步通讯基础类)*/
var xmlHttp=function(sHomeUrl,sServiceName){
	this.preUrl=sHomeUrl+sServiceName+"?.act=";
	this.init();
};
xmlHttp.prototype={
	xml:null,
	action:null,
	param:null,
	init:function(){
		eval("if(window.ActiveXObject){this.xml = new ActiveXObject('Microsoft.XMLHTTP');}else if(window.XMLHttpRequest){this.xml = new XMLHttpRequest();}");
	},
	//初始化
	prepare:function(cid,aid,uid,rid,tid,addParam){
		this.param="";
		if(aid){
			this.action=aid;
		}else{
			throw new Error("Ajx初始化失败: 需要ActionID");
		}
		if(cid){
			this.addParam(".cid",cid);
		}else{
			throw new Error("Ajx初始化失败: 需要ContainerID");
		}
		if(uid){//加入传入的UserID
			this.addParam(".uid",uid);
		}else{
			throw new Error("Ajx初始化失败: 需要用户ID");
		}
		if(rid){
			this.addParam(".rid",rid);
		}
		//如果没有提交附加参数(脚本直接传递的附加可选参数),则必须传入rid
		//否则,不检查rid,即:rid可以为空
		if(addParam!==0 && addParam!=='0'){
			if(!rid){
				throw new Error("Ajx初始化失败: 需要主键ID");
			}
		}
		if(tid){
			this.addParam(".tid",tid);
		}else{
			this.addParam(".tid",cid);
		}
	},
	//提交参数处理
	PostParam:function(cid,flag,otherContainer){
		//增加对textarea提交的控制 flag=2时只提交input不提交textarea
		if(flag===1 || flag===2 || flag==='1' || flag==='2' ){
			this.getParam($(cid).getElementsByTagName('input'));
			if(flag!=2 && flag!='2'){
				this.getParam($(cid).getElementsByTagName('textarea'));
			}
		}
		if(otherContainer){//判断是否有附加参数容器
			if($(otherContainer)){
			this.getParam($(otherContainer).getElementsByTagName('input'));
		}}
		
	},
	//伪同步通讯提交(处理参数)
		//flag 1:提交input和textarea  2:仅提交input 
		//addParam 0:提交附加参数
	  	//otherContainer:其他需要提交的容器
	Post:function(cid,aid,uid,rid,tid,flag,addParam,otherContainer){
		this.prepare(cid,aid,uid,rid,tid,addParam);
		if(addParam===0 || addParam==='0'){/**增加对额外参数的处理*/
			for(var i=7;i<arguments.length;i+=1){
				if(arguments[i].indexOf("=")!=-1){
					this.param = this.param +"&"+ arguments[i];
				}
			}
		}
		this.PostParam(cid,flag,otherContainer);
		//更改为异步提交(需要在外部指定onreadystatechange的处理者)
		this.post(this.action,this.param,true);
	},
	//同步通讯提交
	PostS:function(cid,aid,uid,rid,tid,flag,addParam,otherContainer){
		this.prepare(cid,aid,uid,rid,tid,addParam);
		if(addParam===0 || addParam==='0'){/**增加对额外参数的处理*/
			for(var i=7;i<arguments.length;i+=1){
				if(arguments[i].indexOf("=")!=-1){
					this.param = this.param +"&"+ arguments[i];
				}
			}
		}
		this.PostParam(cid,flag,otherContainer);
		this.post(this.action,this.param,false);
		//同步更新提交后的获取(检测了status)
	    if(this.xml.readyState != 4 || this.xml.status != 200){//描述一种"已加载"状态；此时，响应已经被完全接收。   
    		throw new Error("页面提交失败,readyState="+this.xml.readyState+",status="+this.xml.status);
    	}
	},
	//异步通信提交
	Get:function(cid,aid,uid,rid,tid,handler){
		this.xml.onreadystatechange=handler.bind();
		this.prepare(cid,aid,uid,rid,tid);
		this.PostParam(cid,2);
		this.post(this.action,this.param,true);
	},
	getParam:function(x){//添加容器中的参数
		if(!(x)){return;}
		for (var i = 0; i < x.length; i+=1) {
			if(x[i].id){
				if(x[i].id.substring(0,1)=="."){//如果参数容器ID以.开头,则忽略
					continue;
				}
			}
			try{
				if(x[i].type == "hidden"){	//如果参数类型为隐藏,则名称必须有两段
					var str=x[i].name.split(",");
					if(str.length > 1){
						this.addParam(str[1],x[i].value);
					}
				}else {
					this.addParam(x[i].name,x[i].value);
				}
			}catch(e){
				throw new Error("Ajx参数解析失败: name="+x[i]);
			}
		}
	},
	addParam:function(sParamName,sParamValue){
		if(this.param.length>0){
			this.param+="&";
		}
		this.param+=encodeURI(sParamName)+"="+encodeURI(sParamValue);
	},
	encodeURI:function(s){
		return s.replace(/\&/g, "%26");
	},
	//提交数据(mode:true=异步,false=同步)
	post:function(action,param,mode) {
		this.xml.open("POST", this.preUrl+action, mode);
		this.xml.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
		this.xml.send(param);
	}
};


/**伪同步更新xmlHttp访问实例(仅有一个实例,每次使用时新建赋值)*/
var ajxPost;
/**伪同步刷新时从返回脚本中获取targetId的临时变量*/
var ajxTarget;
/**同步更新xmlHttp访问实例(仅有一个实例,每次解析容器内参数进行post,并返回文本)*/
var ajxPostS=new xmlHttp(WEB_URL,AJXSERVER);
/**后刷新时,存储后刷新命令的临时变量(由具体的刷新脚本将原来绑定在onresize事件上的命令转存到此,等setBind执行完后再执行该脚本*/
var p_func=null;
/**userID*/
var uid=null;
var p_tid;
/**objectID(指AjxServer返回的页面对象的ID)*/
var oid=null;

